package com.starry.module.system.core.checkcode.service.impl;

import cn.hutool.http.HttpStatus;
import com.starry.core.common.execption.ServiceException;
import com.starry.core.redis.service.RedisService;
import com.starry.core.tenant.core.aop.TenantIgnore;
import com.starry.module.system.api.checkcode.domain.qo.CaptchaCreateQo;
import com.starry.module.system.api.checkcode.domain.vo.CaptchaVo;
import com.starry.module.system.core.checkcode.properties.CaptchaProperties;
import com.starry.module.system.core.checkcode.service.CaptchaStrategy;
import com.starry.module.system.core.checkcode.service.CheckCodeService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import static com.starry.module.system.core.redis.RedisKeyConstants.AUTH_CHECK_CODE;

/**
 * @Description 验证码服务-实现类
 * @Author xiaoke
 *
 */
@Service
public class CheckCodeServiceImpl implements CheckCodeService {

    private final ApplicationContext applicationContext;

    private final RedisService redisService;

    private final CaptchaProperties captchaProperties;

    public CheckCodeServiceImpl(ApplicationContext applicationContext, RedisService redisService, CaptchaProperties captchaProperties) {
        this.applicationContext = applicationContext;
        this.redisService = redisService;
        this.captchaProperties = captchaProperties;
    }

    @Override
    @TenantIgnore
    public HashMap<String, String> generate(CaptchaCreateQo qo) {
        CaptchaStrategy captchaStrategy = null;
        try {
            captchaStrategy = (CaptchaStrategy) applicationContext.getBean(qo.getType().getVlaue() + "_captcha");
        } catch (BeansException e) {
            throw new ServiceException("未找到对应的验证码生成器", HttpStatus.HTTP_BAD_REQUEST);
        }
        CaptchaVo result = captchaStrategy.generateCaptcha(qo);
        if (result == null) {
            throw new ServiceException("验证码生成失败", HttpStatus.HTTP_INTERNAL_ERROR);
        }
        HashMap<String, String> resultMap = new HashMap<>();
        String key = result.getKey();
        resultMap.put("img", result.getImg());
        resultMap.put("key", key);
        setCaptchaCache(result, key, qo.getCodeType());
        return resultMap;
    }

    @Override
    @TenantIgnore
    public Boolean check(String key, String value, String type) {
        String result = redisService.getCacheObject(AUTH_CHECK_CODE + type + ":" + key);
        if (result == null) {
            throw new ServiceException("验证码不存在", HttpStatus.HTTP_BAD_REQUEST);
        }
        boolean equals = result.equals(value.toLowerCase());
        if (equals) {
            deleteCaptchaCache(key, type);
        }
        return equals;
    }

    /**
     * 设置验证码缓存
     *
     * @param result 验证码生成结果
     * @param key    key
     */
    private void setCaptchaCache(CaptchaVo result, String key, String type) {
        redisService.setCacheObject(
                AUTH_CHECK_CODE + type + ":" + key, result.getResult(),
                Long.valueOf(captchaProperties.getCacheTime()),
                TimeUnit.MINUTES);
    }

    /**
     * 删除验证码缓存
     *
     * @param key key
     */
    private void deleteCaptchaCache(String key, String type) {
        redisService.deleteObject(AUTH_CHECK_CODE + type + ":" + key);
    }
}
